package com.ccp.dev.system.controller;

import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.consts.SystemConst;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.internationalization.SysBaseController;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.response.ResultData;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.util.FileUtil;
import com.ccp.dev.core.util.RequestUtil;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.core.util.log.SysAuditThreadLocalHolder;
import com.ccp.dev.system.model.Resources;
import com.ccp.dev.system.model.SubSystem;
import com.ccp.dev.system.model.SysRole;
import com.ccp.dev.system.service.ResourcesService;
import com.ccp.dev.system.service.SysOrgService;
import com.ccp.dev.system.util.SubSystemUtil;
import com.ccp.dev.system.util.SysRoleUtil;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 资源管理controller
 *
 * @author nd
 */
@Controller
@Action(ownermodel = SysAuditModelType.SYSTEM_SETTING)
@RequestMapping(UrlConstants.PROJECT_ROOT + UrlConstants.PROJECT_MODULE_SYSTEM + "/sysRes")
public class SysResourcesController extends SysBaseController {

    @Resource
    private ResourcesService resourcesService;

    @Resource
    private SysOrgService sysOrgService;


    @Action(description = "编辑资源信息",
            detail = "给组织【${orgName}】<#if StringUtil.isEmpty(resId)>添加<#else>更新</#if>资源【${resName}】<#if success>成功<#else>失败</#if>",
            exectype = "编辑日志")
    @PostMapping(UrlConstants.MODULE_FUNCTION_ADD_UPDATE)
    @ResponseBody
    public ResultData save(HttpServletRequest request, Resources resources) {
        SysAuditThreadLocalHolder.putParamerter("resId", resources.getResId());
        SysAuditThreadLocalHolder.putParamerter("resName", resources.getResName());
        String orgId = RequestUtil.getString(request, "orgId");
        String tenantId;
        String orgName;
        //业务数据模板中添加为菜单时候使用的
        if (StringUtil.isEmpty(orgId)) {
            tenantId = ContextUtil.getCurrentUserTenantId();
            orgName = ContextUtil.getCurrentOrg().getOrgName();
            resources.setCreator(orgName);
            SysAuditThreadLocalHolder.putParamerter("orgName", orgName);
        } else {
            tenantId = sysOrgService.getTenantIdByOrgId(orgId);
            orgName = sysOrgService.getOneById(orgId).getOrgName();
            resources.setCreator(orgName);
            SysAuditThreadLocalHolder.putParamerter("orgName", orgName);
        }
        try {
            /*
            判断资源别名是否已存在
             */
            boolean isExistsAlias = resourcesService.isExistsAlias(resources.getAlias(), resources.getResId());
            if (isExistsAlias) {
                SysAuditThreadLocalHolder.putParamerter("success", false);
                return getResultDataError("add.resource.failure.exist.resAlias");
            }
            String[] aryName = RequestUtil.getStringAryByStr(request, "name");
            String[] aryUrl = RequestUtil.getStringAryByStr(request, "url");

            resourcesService.saveResources(resources, aryName, aryUrl, tenantId, SubSystemUtil.getCurrentSystemId(request));
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("save.success");
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure");
        }
    }
    @Action(description = "删除资源信息",
            detail = "删除资源<#list resName as item>【${item}】</#list><#if success>成功<#else>失败</#if>",
            exectype = "删除日志")
    @PostMapping(UrlConstants.MODULE_FUNCTION_DELETE)
    @ResponseBody
    public ResultData del(HttpServletRequest request) {
            String[] lAryId = RequestUtil.getStringAryByStr(request, "resId");
            if (lAryId == null) {
                SysAuditThreadLocalHolder.putParamerter("success", false);
                return getResultDataError("delete.failure");
            }
            SysAuditThreadLocalHolder.putParamerter("resName",resourcesService.queryResNameByResIds(Arrays.asList(lAryId)));
        try {
            String msg = resourcesService.delResourcesByIds(lAryId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess(msg);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("delete.failure");
        }
    }

    /**
     * 查询一个资源信息
     *
     * @param request
     * @return
     */
    @Action(description = "查询资源信息",
            detail = "<#assign entity=resourcesService.getOneById(resId)/>查询【${entity.resName}】信息<#if success>成功<#else>失败</#if>",
            exectype = "查询日志")
    @GetMapping(UrlConstants.MODULE_FUNCTION_GET)
    @ResponseBody
    public ResultData get(HttpServletRequest request) {
        try {
            String resId = RequestUtil.getString(request, "resId");
            Resources res = resourcesService.getById(resId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success", 1, res);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operation.failure");
        }

    }

    /**
     * 查询资源树
     *
     * @param request 请求
     * @return ResultData
     */
    @GetMapping(UrlConstants.MODULE_FUNCTION_LIST)
    @ResponseBody
    public ResultData list(HttpServletRequest request) {
        //目前没有用到，用到再编写逻辑！
        return getResultDataSuccess("operation.success", 0, null);
    }

    /**
     * 组织管理 给某租户分配资源页 查询资源树
     *
     * @param request 请求
     * @return ResultData
     */
    @Action(description = "组织管理 给某租户分配资源页 查询资源树",
            detail = "<#assign entity=sysOrgService.getOneById(orgId)/>根据组织【${entity.orgName}】查询上级组织资源<#if success>成功<#else>失败</#if>",
            exectype = "查询日志")
    @GetMapping("/listResForOrgAssignRes")
    @ResponseBody
    public ResultData listForOrgAssignRes(HttpServletRequest request) {
        try{
            /*
            当前节点orgId 查出其租户id;
            非超管用户 要查该用户所属租户下的资源
             */
            String orgId = RequestUtil.getString(request, "orgId");
            int type = RequestUtil.getInt(request, "type",0);
            String systemId = SubSystemUtil.getCurrentSystemId(request);
            List<Resources> resourcesList = resourcesService.queryResTreeData(orgId,type,systemId);
            int count = resourcesList == null ? 0 : resourcesList.size();
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success", count, resourcesList);
        }catch (Exception e){
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataSuccess("operation.failure");
        }

    }

    /**
     * 查询租户资源树
     *
     * @param request 请求
     * @return ResultData
     */
    @Action(description = "查询租户资源树",
            detail = "<#assign entity=sysOrgService.getOneById(orgId)/>根据组织【${entity.orgName}】查询组织资源<#if success>成功<#else>失败</#if>",
            exectype = "查询日志")
    @GetMapping("/listTenantRes")
    @ResponseBody
    public ResultData listTenant(HttpServletRequest request) {
        try{
            Map<String, Object> param = new HashMap<>(3);
            String orgId = RequestUtil.getString(request, "orgId");
            param.put("orgId", orgId);
            String systemId = SubSystemUtil.getCurrentSystemId(request);
            param.put("systemId", systemId);
            List<Resources> resourcesList = resourcesService.queryResourceByTenantSystem(param);
            int count = resourcesList == null ? 0 : resourcesList.size();
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success", count, resourcesList);
        }catch (Exception e){
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataSuccess("operation.failure");
        }
    }

    /**
     * 查询菜单 用户能访问的菜单
     *
     * @param request 请求
     * @return ResultData
     */
    @Action(description = "查询当前登录用户能访问的菜单",
            detail = "查询当前登录用户能访问的菜单<#if success>成功<#else>失败</#if>",
            exectype = "查询日志")
    @GetMapping("/listMenu")
    @ResponseBody
    public ResultData listMenu(HttpServletRequest request) {
        try{
            SubSystem currentSystem = SubSystemUtil.getCurrentSystem(request);
            String systemId = null != currentSystem ? currentSystem.getSystemId() : null;
            SysRole sysRole = SysRoleUtil.getCurrentRole(request);
            String roleId = null != sysRole ? sysRole.getRoleId() : null;
            List<Resources> menuResourcesList = resourcesService.queryListMenu(systemId,roleId);
            int count = menuResourcesList == null ? 0 : menuResourcesList.size();
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success", count, menuResourcesList);
        }catch (Exception e){
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataSuccess("operation.failure");
        }
    }

    /**
     * 导出资源到xml文件
     *
     * @param request  请求
     * @param response 响应
     */
    @Action(description = "导出资源到xml文件",
            detail = "<#assign entity=resourcesService.getOneById(resId)/>导出资源【${entity.resName}】<#if success>成功<#else>失败</#if>",
            exectype = "导出日志")
    @GetMapping("/exportXml")
    public void exportXml(HttpServletRequest request, HttpServletResponse response) {
        String resId = RequestUtil.getString(request, "resId");
        String orgId = RequestUtil.getString(request, "orgId");
        String tenantId = sysOrgService.getTenantIdByOrgId(orgId);
        try {
            Resources resources = resourcesService.getById(resId);
            String fileName = resources.getAlias();
            String strXml = resourcesService.exportXml(resId, tenantId);
            FileUtil.downLoad(request, response, strXml, fileName + ".xml");
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            e.printStackTrace();
        }
    }

    /**
     * 导入xml文件
     *
     * @param request  请求
     * @param response 响应
     */
//    @Action(description = "导入资源文件",
//            detail = "<#assign entity=resourcesService.getOneById(resId)/>给【${entity.resName}】导入资源<#if success>成功<#else>失败</#if>",
//            exectype = "导入日志")
    @PostMapping("/importXml")
    @ResponseBody
    public void importXml(MultipartHttpServletRequest request, HttpServletResponse response) throws Exception {
        PrintWriter writer = response.getWriter();
        String systemId = RequestUtil.getString(request, "systemId");
        String resId = RequestUtil.getString(request, "resId");
        SysAuditThreadLocalHolder.putParamerter("resId", resId);
        String selectTenantId = RequestUtil.getString(request,"selectTenantId");
        MultipartFile fileLoad = request.getFile("xmlFile");
        try {
            resourcesService.importXml(fileLoad.getInputStream(),systemId,selectTenantId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            JSONObject json = JSONObject.fromObject(getResultDataSuccess("operation.success"));
            writer.print(new String(json.toString().getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1));
        } catch (Exception ex) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            JSONObject json = JSONObject.fromObject(getResultDataError("operation.failure"));
            writer.print(new String(json.toString().getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1));
        }
    }

    /**
     * 同级节点排序
     *
     * @param request 携带按顺序排列的同级节点的id数组
     * @return 提示信息
     */
    @Action(description = "资源同级节点排序",
            detail = "资源同级节点排序<#if success>成功<#else>失败</#if>",
            exectype = "编辑日志")
    @PostMapping("/sort")
    @ResponseBody
    public ResultData sortResources(HttpServletRequest request) {
        String[] lAryId = RequestUtil.getStringAryByStr(request, "resIds");
        try {
            resourcesService.updateSn(lAryId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success");
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operation.failure");
        }
    }

    /**
     * 移动节点 将某节点移动到另一个节点下 成为另一个节点的子节点
     *
     * @param request 请求
     * @return 提示信息
     */
    @Action(description = "移动资源节点",
            detail = "<#assign entity=resourcesService.getOneById(sourceId)/><#assign entity1=resourcesService.getOneById(targetId)/>" +
                    "将【${entity.resName}】节点移动到【${entity1.resName}】节点下<#if success>成功<#else>失败</#if>",
            exectype = "编辑日志")
    @PostMapping("/move")
    @ResponseBody
    public ResultData moveResources(HttpServletRequest request) {
        String targetId = RequestUtil.getString(request, "targetId");
        String sourceId = RequestUtil.getString(request, "sourceId");
        try {
            resourcesService.moveResources(sourceId, targetId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success");
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError(e.getMessage());
        }
    }

    /**
     * 验证类是否存在
     *
     * @param request 请求
     * @return ResultData
     */
    @Action(description = "验证类是否存在",
            detail = "验证类【${className}】是否存在",
            exectype = "查询日志")
    @GetMapping("/validClass")
    @ResponseBody
    public ResultData validClass(HttpServletRequest request) {
        String className = RequestUtil.getString(request, "className", "");
        boolean isAllow = resourcesService.validClass(className);
        if (isAllow) {
            return getResultDataSuccess("valid.class.success");
        }
        return getResultDataError("valid.class.failure");
    }

    /**
     * 查询全部资源URL数据
     *
     * @param request 请求
     * @return ResultData
     */
    @Action(description = "查询全部资源URL数据",
            detail = "根据类【${className}】查询全部资源URL数据",
            exectype = "查询日志")
    @GetMapping("/queryAllMenuPath")
    @ResponseBody
    public ResultData queryAllMenuPath(HttpServletRequest request) {
        String classPath = RequestUtil.getString(request, "className");
        String retMsg;
        try {
            retMsg = resourcesService.queryAllMenuPath(classPath);
        } catch (Exception e) {
            return getResultDataError("operation.failure");
        }
        return getResultDataSuccess("operation.success", 1, retMsg);
    }

    /**
     * 查询全部资源URL数据
     *
     * @param request 请求
     * @return ResultData
     * @throws Exception
     */
    @Action(description = "查询全部资源URL数据",
            detail = "根据类【${className}】查询全部资源URL数据",
            exectype = "查询日志")
    @RequestMapping("/getAllMenuPath")
    @ResponseBody
    public ResultData getAllMenuPath(HttpServletRequest request) throws Exception {
        String classPath = RequestUtil.getString(request, "className");
        String retMsg = resourcesService.getAllMenuPath(classPath);
        return new ResultData(0, retMsg, 0L, null);
    }

    /**
     * 资源菜单自动生成
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Action(description = "资源菜单自动生成",
            detail = "根据类【${className}】自动生成资源菜单<#if success>成功<#else>失败</#if>",
            exectype = "编辑日志")
    @PostMapping("/menuAutoGen")
    @ResponseBody
    public ResultData menuAutoGen(HttpServletRequest request) {
        String classPath = RequestUtil.getString(request, "className");
        String parentId = RequestUtil.getString(request, "parentId");
        String orgId = RequestUtil.getString(request, "orgId");
        String tenantId = sysOrgService.getTenantIdByOrgId(orgId);
        String systemId = SubSystemUtil.getCurrentSystemId(request);
        try {
            resourcesService.menuAuto(classPath, parentId, tenantId, systemId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("auto.generate.menu.success");
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("auto.generate.menu.failure");
        }
    }

    /**
     * 根据角色获取租户资源树
     *
     * @return ResultData
     */
    @Action(description = "根据角色获取租户资源树",
            detail = "<#assign entity=sysRoleService.get(roleId)/>根据角色【${entity.roleName}】获取租户资源树<#if success>成功<#else>失败</#if>",
            exectype = "查询日志")
    @ResponseBody
    @GetMapping("/queryTreeByRoleId")
    public ResultData queryTreeByRoleId(@RequestParam String roleId, @RequestParam Short type) {
        try {
            List<Resources> resourcesList = this.resourcesService.queryTreeByRoleId(roleId, type);
            int count = resourcesList == null ? 0 : resourcesList.size();
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("operation.success", count, resourcesList);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operation.failure");
        }
    }

    /**
     * 取得总分类表用于显示树层次结构的分类可以分页列表
     *
     * @param request
     * @return
     */
    @Action(description = "表单添加为菜单异步获取树节点", exectype = "查询日志")
    @RequestMapping("/getSystemTreeData")
    @ResponseBody
    public List<Resources> getSystemTreeData(HttpServletRequest request) {
        String systemId = SubSystemUtil.getCurrentSystemId(request);
        String tenantId = ContextUtil.getCurrentUserTenantId();
        List<Resources> list;
        int status = SystemConst.STATUS_N;
        //获取当前点击的节点id
        String parentId = RequestUtil.getString(request, "resId", SystemConst.DEFAULT_TOP_SOURCE_ID);
        //根据租户ID和系统ID查询资源
        list = resourcesService.getBySysTenResStatusParent(systemId, tenantId, status, parentId);
        for (Resources resources : list) {
            if (null != resources.getCreator() && resources.getCreator().equals(tenantId)) {
                resources.setStatus(SystemConst.STATUS_Y);
            }
        }
        //初始化加载时 加上业务流程系统节点
        if (parentId.equals(SystemConst.DEFAULT_TOP_SOURCE_ID)) {
            Resources parent = resourcesService.getParentResourcesByParentId(systemId, SystemConst.DEFAULT_TOP_SOURCE_ID);
            list.add(parent);
        }
        return list;
    }

    /**
     * 页面跳转 添加|修改页
     */
    @Action(description = "编辑资源页面跳转",exectype = "页面跳转日志")
    @GetMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/add")
    public String viewAddAndEditPage() {
        return "sysRes/add";
    }

    /**
     * 页面跳转 查看页
     */
    @Action(description = "查看资源详细页面跳转",exectype = "页面跳转日志")
    @GetMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/get")
    public String viewInfoGet() {
        return "sysRes/add";
    }

    /**
     * 页面跳转 列表页
     */
    @Action(description = "资源列表页面跳转",exectype = "页面跳转日志")
    @GetMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/list")
    public String viewList() {
        return "sysRes/list";
    }

    /**
     * 页面跳转 列表页
     */
    @Action(description = "查看资源详细页面跳转",exectype = "页面跳转日志")
    @GetMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/view")
    public String viewRes() {
        return "sysRes/view";
    }

    /**
     * 页面跳转 资源图标列表页
     */
    @Action(description = "选择资源图标页面跳转",exectype = "页面跳转日志")
    @GetMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/icons")
    public String iconsRes() {
        return "sysRes/icons";
    }
}
